#include <stdio.h>

enum aenum
{
	aa = -1,
	ab = 0,
	ac = 1,	
};

void swen(enum aenum _ac)
{
	switch (_ac) {
    case aa:
        printf("case aa, _ac=%d\n", _ac);
        break;
	case ab:
        printf("case ab, _ac=%d\n", _ac);
        break;
    case ac:
        printf("case ac, _ac=%d\n", _ac);
        break;
    default:
        printf("case default, _ac=%d\n", _ac);
        break;
	}
}

int main()
{
	enum aenum _ac = (enum aenum)4;
	swen(_ac);

    _ac = (enum aenum)1;
    swen(_ac);

    _ac = (enum aenum)-4;
    swen(_ac);

    return 0;
}

#if 0

g++ -O0 -g -o swen swen.c
./swen
case default, _ac=4
case ac, _ac=1
case default, _ac=-4

g++ -O1 -g -o swen swen.c
./swen
case default, _ac=4
case ac, _ac=1
case default, _ac=-4


    可以看到在O0时，汇编逻辑为：等于0时跳到case B，等于1跳到了case C，不等于-1跳到default， 等于-1到case A。
    而在O1时，汇编逻辑为： 等于0时跳到case B，大于0直接跳到了case C，不等于-1跳到default， 等于-1到case A。

    出错的原因就在于开启编译优化后，GCC对大于零的情况默认其为case C(1)，这里推测是由于test是使用位运算，
    而cmp是使用加减运算，使用test提高了运算效率。

    这是一个GCC4.4版本被反馈过的bug，尽管这个优化很不合理，但依然被作为一个"feature"被保留下来...
    在高版本GCC中，使用-std=c++03 -fstrict-enum选项可以开启这个"特性"，该特性假设编程者会保证enum的取值在其定义范围内。

    最后，解决这个问题的方法有两种，在switch之前做一次enum的范围检查，或者使用更高版本GCC。


#endif
